package com.wmd.validation.validations;

import com.wmd.validation.annotation.ConditionValid;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

/**
 * 类说明
 * 
 * @author yincheng lu
 * @time 2019年1月11日上午11:05:45
 * @Description
 */
public class ConditionValidator implements ConstraintValidator<ConditionValid, Object> {
	private static final Log logger = LogFactory.getLog(ConditionValidator.class);

	private ConditionValid conditionValid;

	@Override
	public void initialize(ConditionValid conditionValid) {
		this.conditionValid = conditionValid;
	}

	@Override
	public boolean isValid(Object value, ConstraintValidatorContext context) {
		// System.out.println("conditionvalidaton:"+this.conditionValid.condition()[0]);
		// logger.info("in ConditionValidator!");
		// logger.info(this.conditionValid.toString());
		// TODO Auto-generated method stub

		if (value == null) {
			return false;
		}
		String fieldName = this.conditionValid.value();
		String[] conditionFieldNames = this.conditionValid.fields();
		if (fieldName == null || fieldName.trim().equals("")) {
			logger.info("ConditionValidator:fieldName is null return true");
			return true;
		}
		if (conditionFieldNames == null || conditionFieldNames.length == 0) {
			logger.info("ConditionValidator:conditionFieldNames is null return true");
			return true;
		}
		Class<?> valueClass = value.getClass();
		switch (this.conditionValid.conditionValidType()) {
		case NOT_NULL:
			try {
				Field field = valueClass.getDeclaredField(fieldName);
				field.setAccessible(true);
				Object data = field.get(value);
				if (data != null) {
					for (String conditionFieldName : conditionFieldNames) {
						Field conditionField = valueClass.getDeclaredField(conditionFieldName);
						conditionField.setAccessible(true);
						Object conditionData = conditionField.get(value);
						if (conditionData == null) {
							return false;
						}
					}
				}
			} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				logger.error(e.getMessage());
				return false;
			}
			break;
		case EQUAL_TO:
			if (this.conditionValid.fieldValue() == null || this.conditionValid.fieldValue().length == 0) {
				return true;
			}
			try {
				Field field = valueClass.getDeclaredField(fieldName);
				field.setAccessible(true);
				Object data = field.get(value);
				if (data != null && Arrays.asList(this.conditionValid.fieldValue()).contains((data + "").trim())) {
					for (String conditionFieldName : conditionFieldNames) {
						Field conditionField = valueClass.getDeclaredField(conditionFieldName);
						conditionField.setAccessible(true);
						Object conditionData = conditionField.get(value);
						// logger.info("conditionData:" + conditionData);
						if (conditionData == null) {
							logger.info("return false");
							return false;
						}

					}
					// logger.info("3");
				}
			} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				logger.error(e.getMessage());
				return false;
			}
			break;
		case EQUAL_TO_AND_CONDITION_EQUAL_TO:
			if (this.conditionValid.fieldValue() == null || this.conditionValid.fieldValue().length == 0
					|| this.conditionValid.fieldsValues().length == 0) {
				return true;
			}
			try {
				Field field = valueClass.getDeclaredField(fieldName);
				field.setAccessible(true);
				Object data = field.get(value);
				List<String> fieldsValues = Arrays.asList(this.conditionValid.fieldsValues());
				if (data != null && Arrays.asList(this.conditionValid.fieldValue()).contains((data + "").trim())) {
					for (String conditionFieldName : conditionFieldNames) {
						Field conditionField = valueClass.getDeclaredField(conditionFieldName);
						conditionField.setAccessible(true);
						Object conditionData = conditionField.get(value);
						// logger.info("conditionData:" + conditionData);
						if (conditionData == null) {
							// logger.info("return false");
							return false;
						} else {
							if (!fieldsValues.contains(conditionData)) {
								return false;
							}
						}

					}
					// logger.info("3");
				}
			} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				logger.error(e.getMessage());
				return false;
			}
			break;
		case VALUE_NULL:
			try {
				Field 	field = valueClass.getDeclaredField(fieldName);
				field.setAccessible(true);
				Object data = field.get(value);
				if(data!=null) {
					return true;
				}else {
					for (String conditionFieldName : conditionFieldNames) {
						Field conditionField = valueClass.getDeclaredField(conditionFieldName);
						conditionField.setAccessible(true);
						Object conditionData = conditionField.get(value);
						if (conditionData == null) {
							return false;
						}
					}
				}
				
			} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			break;
		default:
			break;
		}
		// logger.info("for each not used");
		return true;
	}

}
